﻿namespace Trancity
{
    using Common;
    using Microsoft.DirectX.Direct3D;
    using Microsoft.DirectX.DirectInput;
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    public class MainForm : Form
    {
        //private readonly IContainer _components;
        public static int ticklast;
        private Game _игра;
        public НастройкиЗапуска настройки;

        public MainForm()
        {
            InitializeComponent();
        }

        protected override void Dispose(bool disposing)
        {
        	/*
            if (disposing && (_components != null))
            {
                _components.Dispose();
            }
            base.Dispose(disposing);
            */
        }

        private void InitializeComponent()
        {
            SuspendLayout();
            // 
            // MainForm
            // 
            ClientSize = new Size(346, 345);
            Name = "MainForm";
            ResumeLayout(false);

        }

        [STAThread]
        // ReSharper disable SuggestBaseTypeForParameter
        // ReSharper disable UnusedMember.Local
        private static void Main(string[] args)
        // ReSharper restore UnusedMember.Local
        // ReSharper restore SuggestBaseTypeForParameter
        {
            if (args == null) throw new ArgumentNullException("args");
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            try
            {
                bool flag;
                var app = new MainForm { настройки = new НастройкиЗапуска() };
                app.ЗагрузитьНастройки();
                foreach (var str in args)
                {
                    if (str == "-limited")
                    {
                        Cheats.limited = true;
                    }
                    else
                    {
                        app.настройки.cityFilename = str;
                    }
                }
                MyDirectInput.EnumerateDevices();
                var result = new Options(app).ShowDialog();
                if (result != DialogResult.OK)
                {
                    app.Close();
                    if (result == DialogResult.Ignore)
                    {
                        Application.Run(new Editor());
                    }
                }
                else
                {
                    app.СохранитьНастройки();
                    if (app.настройки.игроки.Length > 1)
                    {
                        var num = 0;
                        foreach (var игрока in app.настройки.игроки)
                        {
                            if (игрока.вИгре)
                            {
                                num++;
                            }
                        }
                        var игрокаArray = new НастройкиЗапускаИгрока[num];
                        var index = 0;
                        foreach (var игрока2 in app.настройки.игроки)
                        {
                            if (!игрока2.вИгре) continue;
                            игрокаArray[index] = игрока2;
                            index++;
                        }
                        app.настройки.игроки = игрокаArray;
                        app.настройки.количествоИгроков = игрокаArray.Length;
                    }
                    flag = !app.настройки.noSound;
                    Рельс.качество_рельсов = app.настройки.качествоРельсов;
                    Road.качествоДороги = app.настройки.качествоРельсов;
                    Рельс.стрелки_наоборот = app.настройки.стрелкиНаоборот;
                    Stop.неЗагружаемКартинки = app.настройки.noStops;
                    try
                    {
                        MyDirect3D.Window_Width = app.настройки.размерЭкрана.Width;
                        MyDirect3D.Window_Height = app.настройки.размерЭкрана.Height;
                        Directory.SetCurrentDirectory(Application.StartupPath + @"\Data");
                        app.Show();
                        if (flag && !MyDirectSound.Initialize(app))
                        {
                            MessageBox.Show("Could not initialize DirectSound.\nПрограмма будет работать без звука.", "Trancity", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            flag = false;
                        }
                        if (!MyDirect3D.Initialize(app, app.настройки.deviceType, app.настройки.createFlags, false))
                        {
                            MessageBox.Show("Could not initialize Direct3D.", "Trancity", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                        }
                        else
                        {
                            //WaitUntilNextFrame();
                            //var num3 = _frameTicks;
                            //_frameTicks = 500;
                            //WaitUntilNextFrame();
                            //_frameTicks = num3;
                            if (!MyDirectInput.Initialize(app, !app.настройки.nonExclusiveKeyboard, !app.настройки.nonExclusiveMouse))
                            {
                                throw new InputException("Could not initialize DirectInput.");
                            }
                            app._игра = new Game();
                            MyDirect3D.splash_title = "Trancity";
                            for (var i = 0; i < 0xffffff; i += 0x101010)
                            {
                                //WaitUntilNextFrame();
                                MyDirect3D.Splash(i);
                            }
                            MyDirect3D.Splash(0xffffff);
                            MyDirect3D.load_status = 0;
                            MyDirect3D.status_string = "Загрузка города...";
                            MyDirect3D.Splash();
                            app._игра.мир = new World();
                            if (app.настройки.cityFilename != null)
                            {
                                app._игра.мир.ЗагрузитьГород(app.настройки.cityFilename);
                            }
                            app._игра.мир.time = app.настройки.начальноеВремя;
                            if (app._игра.мир.time < 10800.0)
                            {
                                app._игра.мир.time += 86400.0;
                            }
                            app._игра.мир.ДобавитьТрамваи(app.настройки, app._игра);
                            MyDirect3D.status_string = "Загрузка моделей...";
                            MyDirect3D.Splash();
                            app._игра.мир.Create_Meshes();
                            if (flag)
                            {
                                try
                                {
                                    if (MyDirectInput.Acquire())
                                    {
                                        app._игра.мир.CreateSound();
                                    }
                                    else
                                    {
                                        MessageBox.Show("Sound buffers создавались, когда приложение было неактивно.\nПрограмма будет работать без звука.", "Trancity", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                        flag = false;
                                    }
                                }
                                catch
                                {
                                    MessageBox.Show("Could create sound buffers.\nПрограмма будет работать без звука.", "Trancity", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                                    flag = false;
                                }
                            }
                            while (app.Created)
                            {
                                if (!MyDirectInput.Process() && MyDirectInput.alt_f4)
                                {
                                    MyDirectInput.Free();
                                    app.Close();
                                    return;
                                }
                                app._игра.Process_Input();
                                if (app._игра.активна)
                                {
                                    app._игра.мир.Обновить(app._игра.игроки);
                                }
                                else
                                {
                                    app._игра.мир.Обновить_время();
                                }
                                if (flag)
                                {
                                    app._игра.мир.UpdateSound(app._игра.игроки, app._игра.активна);
                                }
                                app._игра.Render();
                                //WaitUntilNextFrame();
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        var str2 = "Unhandled exception of type " + exception.GetType() + "\n" + exception;
                        app.Close();
                        MessageBox.Show(str2 + "\n\nПожалуйста, сообщите создателю игры об этой ошибке.", "Trancity", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                    }
                }
            }
            catch (Exception exception2)
            {
                try
                {
                    MessageBox.Show(("Произошла ошибка во время операций с настройками или в окне опций.\nUnhandled exception of type " + exception2.GetType() + "\n" + exception2) + "\n\nПожалуйста, сообщите создателю игры об этой ошибке.", "Trancity", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
                catch
                {
                    MessageBox.Show("Произошла неизвестная ошибка.\n\nПожалуйста, сообщите создателю игры об этой ошибке.", "Trancity", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
            }
        }

        //public static void WaitUntilNextFrame()
        //{
        //    int tickCount;
        //    do
        //    {
        //        Msg message = new Msg();
        //        if (Common.Windows.Windows.GetMessage(ref message, IntPtr.Zero, 0, 0))
        //        {
        //            Common.Windows.Windows.TranslateMessage(ref message);
        //            Common.Windows.Windows.DispatchMessage(ref message);
        //        }
        //        Application.DoEvents();
        //        tickCount = Environment.TickCount;
        //    }
        //    while ((tickCount - ticklast) < _frameTicks);
        //    ticklast = tickCount;
        //}

        private void ЗагрузитьНастройки()
        {
            Directory.SetCurrentDirectory(Application.StartupPath);
            настройки.размерЭкрана = new Size(Ini.ReadInt(@".\options.ini", "Common", "размер_экрана_x", 0x500), Ini.ReadInt(@".\options.ini", "Common", "размер_экрана_y", 960));
            настройки.начальноеВремя = Ini.ReadInt(@".\options.ini", "Common", "начальноеВремя", 0x6270);
            настройки.количествоОстальныхТрамваев = Ini.ReadInt(@".\options.ini", "Common", "количество_трамваев", 0);
            настройки.автоматическоеУправление = Ini.ReadBool(@".\options.ini", "Common", "автоматическоеУправление", false);
            настройки.поворачиватьКамеру = Ini.ReadBool(@".\options.ini", "Common", "поворачиватьКамеру", true);
            настройки.deviceType = (Microsoft.DirectX.Direct3D.DeviceType)Ini.ReadInt(@".\options.ini", "Common", "deviceType", 1);
            настройки.createFlags = (CreateFlags)Ini.ReadInt(@".\options.ini", "Common", "createFlags", 0x40);
            настройки.количествоИгроков = Ini.ReadInt(@".\options.ini", "Common", "количествоИгроков", 0);
            try
            {
                настройки.качествоРельсов = double.Parse(Ini.Read(@".\options.ini", "Common", "качествоРельсов", "4"));
            }
            catch
            {
                настройки.качествоРельсов = 4.0;
            }
            настройки.cityFilename = Ini.Read(@".\options.ini", "Common", "cityFilename", "");
            if (настройки.cityFilename == "")
            {
                настройки.cityFilename = null;
            }
            настройки.стрелкиНаоборот = Ini.ReadBool(@".\options.ini", "Common", "стрелкиНаоборот", false);
            настройки.noSound = Ini.ReadBool(@".\options.ini", "Common", "noSound", false);
            настройки.noStops = Ini.ReadBool(@".\options.ini", "Common", "noStops", false);
            настройки.nonExclusiveKeyboard = Ini.ReadBool(@".\options.ini", "Common", "nonExclusiveKeyboard", false);
            настройки.nonExclusiveMouse = Ini.ReadBool(@".\options.ini", "Common", "nonExclusiveMouse", false);
            настройки.игроки = new НастройкиЗапускаИгрока[настройки.количествоИгроков];
            for (var i = 0; i < настройки.количествоИгроков; i++)
            {
                var section = string.Format("Player {0}", i);
                настройки.игроки[i].имя = Ini.Read(@".\options.ini", section, "имя", "Игрок " + i);
                настройки.игроки[i].inputGuid = new Guid(Ini.Read(@".\options.ini", section, "inputGuid", SystemGuid.Keyboard.ToString()));
                настройки.игроки[i].подвижнойСостав = Ini.Read(@".\options.ini", section, "подвижнойСостав", "");
                настройки.игроки[i].маршрут = Ini.ReadInt(@".\options.ini", section, "маршрут", 0);
                настройки.игроки[i].наряд = Ini.ReadInt(@".\options.ini", section, "наряд", 0);
                настройки.игроки[i].вИгре = Ini.ReadBool(@".\options.ini", section, "вИгре", false);
            }
        }

        private void СохранитьНастройки()
        {
            Directory.SetCurrentDirectory(Application.StartupPath);
            Ini.Write(@".\options.ini", "Common", "размер_экрана_x", настройки.размерЭкрана.Width.ToString());
            Ini.Write(@".\options.ini", "Common", "размер_экрана_y", настройки.размерЭкрана.Height.ToString());
            Ini.Write(@".\options.ini", "Common", "начальноеВремя", настройки.начальноеВремя.ToString());
            Ini.Write(@".\options.ini", "Common", "количество_трамваев", настройки.количествоОстальныхТрамваев.ToString());
            Ini.Write(@".\options.ini", "Common", "автоматическоеУправление", настройки.автоматическоеУправление.ToString());
            Ini.Write(@".\options.ini", "Common", "поворачиватьКамеру", настройки.поворачиватьКамеру.ToString());
            Ini.Write(@".\options.ini", "Common", "deviceType", ((int)настройки.deviceType).ToString());
            Ini.Write(@".\options.ini", "Common", "createFlags", ((int)настройки.createFlags).ToString());
            Ini.Write(@".\options.ini", "Common", "количествоИгроков", настройки.количествоИгроков.ToString());
            Ini.Write(@".\options.ini", "Common", "качествоРельсов", настройки.качествоРельсов.ToString());
            if (настройки.cityFilename != null)
            {
                Ini.Write(@".\options.ini", "Common", "cityFilename", настройки.cityFilename);
            }
            else
            {
                Ini.Write(@".\options.ini", "Common", "cityFilename", "");
            }
            Ini.Write(@".\options.ini", "Common", "стрелкиНаоборот", настройки.стрелкиНаоборот.ToString());
            Ini.Write(@".\options.ini", "Common", "noSound", настройки.noSound.ToString());
            Ini.Write(@".\options.ini", "Common", "noStops", настройки.noStops.ToString());
            Ini.Write(@".\options.ini", "Common", "nonExclusiveKeyboard", настройки.nonExclusiveKeyboard.ToString());
            Ini.Write(@".\options.ini", "Common", "nonExclusiveMouse", настройки.nonExclusiveMouse.ToString());
            for (var i = 0; i < настройки.количествоИгроков; i++)
            {
                var section = string.Format("Player {0}", i);
                Ini.Write(@".\options.ini", section, "имя", настройки.игроки[i].имя);
                Ini.Write(@".\options.ini", section, "inputGuid", настройки.игроки[i].inputGuid.ToString());
                Ini.Write(@".\options.ini", section, "подвижнойСостав", настройки.игроки[i].подвижнойСостав);
                Ini.Write(@".\options.ini", section, "маршрут", настройки.игроки[i].маршрут.ToString());
                Ini.Write(@".\options.ini", section, "наряд", настройки.игроки[i].наряд.ToString());
                Ini.Write(@".\options.ini", section, "вИгре", настройки.игроки[i].вИгре.ToString());
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct НастройкиЗапуска
        {
            public int начальноеВремя;
            public Size размерЭкрана;
            public int количествоОстальныхТрамваев;
            public bool автоматическоеУправление;
            public bool поворачиватьКамеру;
            public Microsoft.DirectX.Direct3D.DeviceType deviceType;
            public CreateFlags createFlags;
            public int количествоИгроков;
            public double качествоРельсов;
            public НастройкиЗапускаИгрока[] игроки;
            public string cityFilename;
            public bool стрелкиНаоборот;
            public bool noSound;
            public bool noStops;
            public bool nonExclusiveKeyboard;
            public bool nonExclusiveMouse;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct НастройкиЗапускаИгрока
        {
            public string имя;
            public Guid inputGuid;
            public string подвижнойСостав;
            public int маршрут;
            public int наряд;
            public bool вИгре;
        }
    }
}

